package com.tang.plugin.model;

import java.util.HashMap;
import java.util.Map;

public class FileTreeDsl extends FileTreeNode {

    public FileTreeDsl(String name, boolean isDir, FileTreeNode parent) {
        super(name, isDir, parent);
    }

    public void invoke(Callback callback) {
        if(callback != null) {
            callback.invoke(this);
        }
    }

    public FileTreeDsl(Callback callback) {
        super();
        if (callback != null) {
            callback.invoke(this);
        }
    }

    public FileTreeDsl placeHolder(String name, String value) {
        if (getPlaceHolderMap() == null) {
            setPlaceHolderMap(new HashMap<>());
        }
        getPlaceHolderMap().put(name, value);
        return this;
    }

    public FileTreeDsl fileTemplate(String name, String template) {
        if (getFileTemplate() == null) {
            setFileTemplate(new HashMap<>());
        }
        getFileTemplate().put(name, template);
        return this;
    }

    public FileTreeDsl dir(String path, Callback callback) {
        if (!isDir()) {
            if(callback != null){
                callback.invoke(this);
            }
            return this;
        }
        FileTreeDsl newNode = new FileTreeDsl(path, true, this);
        if (addChild(newNode)) {
            newNode.invoke(callback);
        }
        return this;
    }

    public FileTreeDsl include(FileTreeDsl other) {
        return include(other, false);
    }

    public FileTreeDsl include(FileTreeDsl other, boolean override) {
        if (!isDir()) {
            return this;
        }
        other.getChildren().forEach((it) -> {
            FileTreeNode includeChild = it.copy();
            if (other.getPlaceHolderMap() != null) {
                if (includeChild.getPlaceHolderMap() == null) {
                    includeChild.setPlaceHolderMap(new HashMap<>());
                }
                other.getPlaceHolderMap().forEach((k, v) -> {
                    Map<String, String> templateInherit = getFileTemplateInherit();
                    if (templateInherit != null && !templateInherit.containsKey(k)) {
                        includeChild.getPlaceHolderMap().put(k, v);
                    }
                });
            }
            if (other.getFileTemplate() != null) {
                if (includeChild.getFileTemplate() == null) {
                    includeChild.setFileTemplate(new HashMap<>());
                }
                other.getFileTemplate().forEach((k, v) -> {
                    Map<String, String> fileTemplate = getFileTemplate();
                    if (fileTemplate != null && !fileTemplate.containsKey(k)) {
                        includeChild.getFileTemplate().put(k, v);
                    }
                });
            }
            addChild(includeChild, override);
        });
        return this;
    }

    public FileTreeDsl file(String name) {
        if (!isDir()) {
            getPlaceHolder(name).forEach((it) -> {
                Map<String, String> placeHolderInherit = getPlaceHolderInherit();
                if (placeHolderInherit != null && !placeHolderInherit.containsKey(it)) {
                    placeHolder(it, "");
                }
            });
        }
        addChild(new FileTreeNode(name, false, this));
        return this;
    }

    public FileTreeDsl addFileTemplates(Map<String, String> placeHolder) {
        if(getFileTemplate() == null){
            setFileTemplate(new HashMap<>());
        }
        getFileTemplate().putAll(placeHolder);
        return this;
    }

    public FileTreeDsl addPlaceHolders(Map<String, String> placeHolder) {
        if(getPlaceHolderMap() == null){
            setPlaceHolderMap(new HashMap<>());
        }
        getPlaceHolderMap().putAll(placeHolder);
        return this;
    }

    public interface Callback {
        void invoke(FileTreeDsl node);
    }

}
